﻿using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using SharePoint.Orm.TestHelpers;

namespace SharePoint.Orm.Caml {
	[TestFixture]
	public class LinqCamlRunnerTest : TestBase {
		private readonly List<Car> _testData = new List<Car> {
       		new Car {Make = "Porche", Model = "Boxster"},
       		new Car {Make = "Porche", Model = "911"},
       		new Car {Make = "Cadillac", Model = "CTS"},
       		new Car {Make = "Porche", Model = "Cayenne"},
       		new Car {Make = "Cadillac", Model = "SRX"}
       	};

		[Test]
		public void TestOrderBy_Enumerable() {
			CamlOrderBy orderBy = new CamlOrderBy();
			orderBy.Fields.Add(new CamlFieldRef("Make"));
			Car[] results = new LinqCamlRunner().RunOrderBy(_testData, orderBy).ToArray();
			IEnumerable<Car> expected = _testData.OrderBy(c => c.Make);
			EnumerableAssert.AreEqual(expected, results);
		}

		[Test]
		public void TestOrderBy_Queryable() {
			CamlOrderBy orderBy = new CamlOrderBy();
			orderBy.Fields.Add(new CamlFieldRef("Make"));
			Car[] results = new LinqCamlRunner().RunOrderBy(_testData.AsQueryable(), orderBy).ToArray();
			IEnumerable<Car> expected = _testData.OrderBy(c => c.Make);
			EnumerableAssert.AreEqual(expected, results);
		}

		[Test]
		public void TestOrderBy_ThenBy() {
			CamlOrderBy orderBy = new CamlOrderBy();
			orderBy.Fields.Add(new CamlFieldRef("Make"));
			orderBy.Fields.Add(new CamlFieldRef("Model"));
			Car[] results = new LinqCamlRunner().RunOrderBy(_testData, orderBy).ToArray();
			IEnumerable<Car> expected = _testData.OrderBy(c => c.Make).ThenBy(c => c.Model);
			EnumerableAssert.AreEqual(expected, results);
		}

		[Test]
		public void TestOrderBy_Descending() {
			CamlOrderBy orderBy = new CamlOrderBy();
			orderBy.Fields.Add(new CamlFieldRef("Make") { Ascending = false });
			Car[] results = new LinqCamlRunner().RunOrderBy(_testData, orderBy).ToArray();
			IEnumerable<Car> expected = _testData.OrderByDescending(c => c.Make);
			EnumerableAssert.AreEqual(expected, results);
		}

		[Test]
		public void TestWhere_Enumerable() {
			CamlWhere where = new CamlWhere {
				Root = new CamlEquals {
					FieldRef = new CamlFieldRef("Make"),
					Value = new CamlValue(CamlValueType.String, "Porsche")
				}
			};
			Car[] results = new LinqCamlRunner().RunWhere(_testData, where).ToArray();
			IEnumerable<Car> expected = _testData.Where(c => c.Make == "Porsche");
			EnumerableAssert.AreEqual(expected, results);
		}

		[Test]
		public void TestWhere_Queryable() {
			CamlWhere where = new CamlWhere {
				Root = new CamlEquals {
					FieldRef = new CamlFieldRef("Make"),
					Value = new CamlValue(CamlValueType.String, "Porsche")
				}
			};
			Car[] results = new LinqCamlRunner().RunWhere(_testData.AsQueryable(), where).ToArray();
			IEnumerable<Car> expected = _testData.Where(c => c.Make == "Porsche");
			EnumerableAssert.AreEqual(expected, results);
		}

		[Test]
		public void TestWhere_WithAnd() {
			CamlWhere where = new CamlWhere {
				Root = new CamlAnd {
					First = new CamlEquals {
						FieldRef = new CamlFieldRef("Make"),
						Value = new CamlValue(CamlValueType.String, "Porsche")
					},
					Second = new CamlEquals {
						FieldRef = new CamlFieldRef("Model"),
						Value = new CamlValue(CamlValueType.String, "Boxster")
					}
				}
			};
			Car[] results = new LinqCamlRunner().RunWhere(_testData, where).ToArray();
			IEnumerable<Car> expected = _testData.Where(c => c.Make == "Porsche" && c.Model == "Boxster");
			EnumerableAssert.AreEqual(expected, results);
		}

		private class Car {
			public string Make { get; set; }
			public string Model { get; set; }
		}
	}

}
